#ifndef _DCM_INTERFACE_
#define _DCM_INTERFACE_

#include <string>
#include "../LibCommon/data_define/Result.h"
#include "../LibCommon/CommonInterface.h"

#include "IndexRange.h"
#include "Segment.h"


/**
 * Base information of CacheItem. Used by user to obtain the information.
 **/
class tCacheItemInfo
{
public:
	tInt128	m_ContentID;
	unsigned int m_SegmentUnitSize;
	UINT64 m_FinalIndex;
	unsigned int m_FinalSegmentSize;
	unsigned int m_Usage;
	std::string m_strInfoFilePath;

	tCacheItemInfo():m_ContentID(0), m_SegmentUnitSize(0), m_FinalIndex(0),
		m_FinalSegmentSize(0), m_Usage(0)
	{
	}
};

/**
 * IDataCacheItem interface is used for get/set data from/to cache item. 
 */ 
class IDataCacheItem : public IBaseInterface
{
public:
	/**
	 * Get ContentID of this DataCacheItem.
	 **/
	virtual tInt128 GetContentID() = 0;
	/**
	 * "ReadData" method gets a block of data from DataCacheItem from a specified position.
	 * Param:
	 *     pBuffer: User provided buffer for receiving data.
	 *     Offset: The offset from the start of the DataCache.
	 *     BufferLength: The length of user provided buffer.
	 *     pReadCount: How many data have been read to user's buffer.
	 *     bWait: Whether this function should be blocked when not enough data can be read.
	 *     Timeout: If bWait is set, Timeout indicate how long user wish to wait for.
	 * Return:
	 *     RET_OK: All required data have been read to user's buffer, and pReadCount is updated.
	 *     RET_ERROR: No data can be read due to general error. pReadCount will be set to zero.
	 *     RET_TIMEOUT: The read operation is timeout, and not all data have been read to user's buffer.
	 *                  The pReadCount is updated, and user can check how many data have been read.
	 */
	virtual eResult ReadData(char * pBuffer, unsigned int Offset, unsigned int BufferLength, 
								unsigned int * pReadCount, bool bWait, unsigned int Timeout, HANDLE hBreakEvent = 0) = 0;

	/**
	 * "WriteData" Write a block of data to DataCacheItem. Because underlying structure is segmented, the data
	 * will be cached firstly if it don't consist the completed segment, so make sure the total size written 
	 * by the serials of "WriteData" function call is multiple of segment unit size, otherwise, the incompleted 
	 * segment will not be saved.
	 * Param:
	 *     pBuffer: User provided buffer which contian data.
	 *     Offset: the start position from beginning of DataCache.
	 *     BufferLength: Length of the Buffer.
	 *     bFinal: Whether the writing data is end of the whold DataCache. It's very important for CacheItem
	 *             to maintain the last few bytes of content.
	 * Return:
	 *     RET_OK: Successfully writed data to DataCacheItem.
	 *     RET_ERROR: Can not write data to DataCacheItem.
	 **/
	virtual eResult WriteData(const char * pBuffer, unsigned int Offset, unsigned int BufferLength, bool bFinal) = 0;
	virtual	eResult WriteExpressData(const char * pBuffer, unsigned int Offset, unsigned int BufferLength) = 0;

	/**
	 * Retrieve the Segment Unit Size.
	 **/
	virtual unsigned int GetSegmentUnitSize() = 0;

	/**
	  * Read a segment from CacheItem.
	  * Param:
	  *    Index: The index of segment.
	  *    pSegmentData: Segment buffer pointer.
	  *    SegmentSize: Size of Segment. You set the buffer size of segment, it also
	  *                 return the actual size of segment returned.
	  * Return:
	  *    RET_OK: The Segment is read successfully.
	  *    RET_ERROR: Can not read the required segment.
	  **/
	//virtual eResult GetSegment(UINT64 Index, char * pSegmentData, unsigned int &SegmentSize) = 0;
	virtual eResult GetSegment(UINT64 Index, tSegment & Seg) = 0;
	virtual eResult FreeSegment(tSegment & Seg) = 0;

	/**
	  * Write a segment to CacheItem.
	  * Param:
	  *    Index: The index of segment.
	  *    pSegmentData: Segment buffer pointer.
	  *    SegmentSize: Size of SegmentData.
	  * Return:
	  *    RET_OK: The Segment is written successfully.
	  *    RET_ERROR: Can not write the required segment.
	 **/
	//virtual eResult SetSegment(UINT64 Index, const char * pSegmentData, unsigned int SegmentSize) = 0;
	virtual eResult SetSegment(UINT64 Index, const tSegment & Seg) = 0;

	/**
	 * Whether there has been segment in the cache item.
	 * Param:
	 *    Index: The index of segment.
	 * Return:
	 *    RET_OK: The segment is existed.
	 *    RET_ERROR: The segment is not existed.
	 **/
	virtual eResult DetectSegment(UINT64 Index) = 0;

	/**
	 * Set the finial segment's size and index.
	 **/
	virtual eResult SetFinalSegment(UINT64 Index, unsigned int Size) = 0;

	/**
	 * Get finial segment's index.
	 **/
	virtual UINT64 GetFinalSegment(unsigned int * pFinalSegSize) = 0;

	/**
	 * Get current available segment index's range.
	 **/
	virtual void GetIndexRange(tIndexRange * pIR) = 0;

	/**
	 * Get Latest segment written.
	 **/
	virtual UINT64 GetLatestSegmentIndex() = 0;

	virtual unsigned int GetTotalSize() = 0;
	virtual void SetTotalSize(unsigned int size) = 0;
	virtual void Hit() = 0;
	virtual unsigned int GetCachedDataSize() = 0;
};

class ICacheBufferLeak : public IBaseInterface
{
public:
	virtual unsigned int GetFreshDatasize() = 0;
	virtual void LeakFreshData(unsigned int size) = 0;
	virtual void FlushFreshData() = 0;
};

class IDataCacheManager : public IBaseInterface
{
public:
	/**
	 * Set total size of the Cache space on disk.
	 **/ 
	virtual void SetCacheSize(UINT64 Size) = 0;

	/**
	 * Set the path where to place the cache file.
	 **/
	virtual void SetCachePath(const char * Path) = 0;

	/**
	 * Initialize the DataCacheManager.
	 * Return:
	 *     RET_OK: The initialization is OK.
	 *     RET_ERROR: Can not initialize the DataCacheManager.
	 **/
	virtual eResult InitCacheMgr(UINT64 Size, const char * Path) = 0;

	/**
	 * UnInitialize the DataCacheManager.
	 **/
	virtual eResult UnInitCacheMgr() = 0;

	/**
	 * Create a empty DataCacheItem with ContentID.
	 * Param:
	 *     ContentID: The Identify of the Content.
	 *     strWho: User Identifier.
	 * Return:
	 *     IDataCacheItem: Interface of the new DataCacheItem. If this value is NULL, 
	 *                     the creation is failed. If the CacheItem is already existed,
	 *                     the method return the existed cache item.
	 **/
	virtual IDataCacheItem* CreateCacheItem(tInt128 ContentID, const char * strWho) = 0;
	
	/**
	 * Get existing DataCacheItem. If this cache itme is not loaded, DataCacheManager
	 * will try to load it.
	 * Param:
	 *    ContentID: The Identify of the Content.
	 *    strWho: a string which indicates who get this CacheItem.
	 * Return:
	 *    IDataCacheItem: Interface of the DataCacheItem. If this value is NULL,
	 *                    the operation is failed.
	 * Notice:
	 *    When this method is successed, the DataCacheItem's reference is increased.
	 *    User should can IDataCacheItem::Release() to reduce the reference. Otherwise,
	 *    memory leak may occur.
	 **/
	virtual IDataCacheItem * GetCacheItem(tInt128 ContentID, const char * strWho) = 0;

	virtual eResult DeleteCacheItem(tInt128 ContentID) = 0;

	/**
	 * Get list of all content cache information.
	 * Param:
	 *    pCacheItemInfoList: pointer to a array list which receive cache info.
	 *    ListLength: The Length of the pCacheItemInfoList. If this is 0, DataCacheManager
	 *                will give you the correct length of existed cache item.
	 * Return:
	 *    RET_OK: Successfully.
	 *    RET_ERROR: Some error happen.
	 **/
	virtual eResult GetCachedItemInfo(tCacheItemInfo * pCacheItemInfoList, unsigned int * ListLength) = 0;
};

class ITVCacheItem : public IBaseInterface
{
public:
	/**
	 * Get ContentID of this Item.
	 **/
	virtual tInt128 GetContentID() = 0;

	/**
	 * Retrieve the Segment Unit Size.
	 **/
	virtual unsigned int GetSegmentUnitSize() = 0;

	/**
	  * Read a segment from CacheItem.
	  * Param:
	  *    Index: The index of segment.
	  *    pSegmentData: Segment buffer pointer.
	  *    SegmentSize: Size of Segment. You set the buffer size of segment, it also
	  *                 return the actual size of segment returned.
	  * Return:
	  *    RET_OK: The Segment is read successfully.
	  *    RET_ERROR: Can not read the required segment.
	  **/
	//virtual eResult GetSegment(UINT64 Index, char * pSegmentData, unsigned int &SegmentSize) = 0;
	virtual eResult GetSegment(UINT64 Index, tSegment & Seg) = 0;

	/**
	  * Write a segment to CacheItem.
	  * Param:
	  *    Index: The index of segment.
	  *    pSegmentData: Segment buffer pointer.
	  *    SegmentSize: Size of SegmentData.
	  * Return:
	  *    RET_OK: The Segment is written successfully.
	  *    RET_ERROR: Can not write the required segment.
	 **/
	//virtual eResult SetSegment(UINT64 Index, const char * pSegmentData, unsigned int SegmentSize) = 0;
	virtual eResult SetSegment(UINT64 Index, const tSegment & Seg) = 0;

	/**
	 * Whether there has been segment in the cache item.
	 * Param:
	 *    Index: The index of segment.
	 * Return:
	 *    RET_OK: The segment is existed.
	 *    RET_ERROR: The segment is not existed.
	 **/
	virtual eResult DetectSegment(UINT64 Index) = 0;

	/**
	 * Get current available segment index's range.
	 **/
	virtual void GetIndexRange(tIndexRange * pIR) = 0;
	
	virtual void Reset() = 0;
    //void SetContentID(tInt128 ContentID);

};

//===================================================================
// This interface is used for TV Service Cache.
//-------------------------------------------------------------------
class ITVServiceCacheInfo : public IBaseInterface
{
public:
	virtual unsigned int GetHistorySize() = 0;
	virtual int GetRange(UINT64 *uHead, UINT64 *uTail) = 0;
};

class ITVCacheManager : public IBaseInterface
{
public:
	virtual ITVCacheItem * GetTVItem(tInt128 iContentID, const char * strWho) = 0;
	virtual ITVCacheItem * CreateTVItem(tInt128 iContentID, const char * strWho) = 0;
	virtual eResult RemoveTVItem(tInt128 iContentID, const char * strWho) = 0;
};

#endif